package com.stake.web.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;
import javax.servlet.http.HttpSession;

import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.google.appengine.api.channel.ChannelMessage;
import com.google.appengine.api.channel.ChannelService;
import com.google.appengine.api.channel.ChannelServiceFactory;
import com.stake.entity.UserInfo;
import com.stake.model.ChatContent;
import com.stake.model.User;
import com.stake.util.AppConstants;

//@Controller
//@RequestMapping("/chat")
public class ChatController {

	//@Autowired
	//@Qualifier("persistenceManagerFactory")
	PersistenceManagerFactory persistenceManagerFactory;

	public static final org.apache.log4j.Logger logger = org.apache.log4j.Logger
			.getLogger(ChatController.class);


	//@RequestMapping("/showUsers.htm")
	public ModelAndView showChatUsers() {
		Authentication authentication = SecurityContextHolder.getContext()
				.getAuthentication();
		UserInfo thisUser = (UserInfo) authentication.getPrincipal();
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("users", getUsers(thisUser.getUserName()));
		return new ModelAndView("chatUsers", model);
	}

	@SuppressWarnings("unchecked")
	private List<User> getUsers(String thisUser) {
		List<User> users = new ArrayList<User>();
		PersistenceManager manager = persistenceManagerFactory
				.getPersistenceManager();
		Query query = manager.newQuery(UserInfo.class);
		List<UserInfo> UserEntities = (List<UserInfo>) query.execute();
		for (UserInfo info : UserEntities) {
			User user = new User();
			user.setUserName(info.getUserName());
			user.setIsOnline(info.getLastTimeStampMillis() == null ? false : getMinutesAfter(info.getLastTimeStampMillis()) < 5l);
			if (!user.getUserName().equals(thisUser))
				users.add(user);
		}
		return users;
	}

	private long getMinutesAfter(long millis) {
		long diff = new Date().getTime() - millis;
		return diff / (1000 * 60);
	}

	//@RequestMapping("/activateChat.htm")
	public @ResponseBody
	String activateChat(HttpSession session) {
		Authentication authentication = SecurityContextHolder.getContext()
				.getAuthentication();
		UserInfo thisUser = (UserInfo) authentication.getPrincipal();
		ChannelService channelService = ChannelServiceFactory
				.getChannelService();
		String token = null;
		String persistedToken = (String) session
				.getAttribute(AppConstants.USER_TOKEN_SESSION_ATTR);
		if (persistedToken == null) {
			token = channelService.createChannel(thisUser.getUserName());
			session.setAttribute(AppConstants.USER_TOKEN_SESSION_ATTR, token);
		} else {
			token = persistedToken;
		}
		session.setAttribute(AppConstants.IS_CHAT_ENABLED_ATTR, "true");
		logger.info("token for this user : " + token);
		return token;
	}

	//@RequestMapping("/sendChat5.htm")
	public @ResponseBody
	String sendChat5(@ModelAttribute("chatContent") ChatContent chatContent) {
		Authentication authentication = SecurityContextHolder.getContext()
				.getAuthentication();
		UserInfo user = (UserInfo) authentication.getPrincipal();
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("message", user.getUserName() + " : " + chatContent.getText());
		model.put("window", user.getUserName());
		JSONObject jsonResp = new JSONObject(model);
		ChannelService channelService = ChannelServiceFactory
				.getChannelService();
		channelService.sendMessage(new ChannelMessage(chatContent.getToUser(),
				jsonResp.toString()));
		return "me : " + chatContent.getText();
	}

	@SuppressWarnings("unchecked")
	//@RequestMapping("/showChatWindow.htm")
	public @ResponseBody
	String renderHtml5ChatWindow(@RequestParam("toUser") String toUser)
			throws Exception {
		PersistenceManager manager = persistenceManagerFactory
				.getPersistenceManager();
		Query query = manager.newQuery(UserInfo.class);
		query.setFilter("userName == userNameParam");
		query.declareParameters("String userNameParam");
		List<UserInfo> userEntities = (List<UserInfo>) query.execute(toUser);
		UserInfo windowUser = null;
		if (userEntities.size() == 0) {
			throw new Exception("user does not exist");
		} else {
			windowUser = userEntities.get(0);
		}

		Map<String, Object> model = new HashMap<String, Object>();

		model.put("toUser", toUser);
		model.put("headerName",
				windowUser.getFirstName() + " " + windowUser.getLastName());
		model.put("handleId", windowUser.getUserName() + "handle");
		model.put("inputId", windowUser.getUserName() + "input");
		model.put("inputTextId", windowUser.getUserName() + "input_text");
		model.put("formId", windowUser.getUserName() + "form");
		model.put("svgId", windowUser.getUserName() + "svg");
		JSONObject jsonResp = new JSONObject(model);
		return jsonResp.toString();
	}

	//@RequestMapping("/heartBeat.htm")
	public @ResponseBody
	String heartBeat() {
		Authentication authentication = SecurityContextHolder.getContext()
				.getAuthentication();
		UserInfo user = (UserInfo) authentication.getPrincipal();
		insertActiveUser(user.getUserName());
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("onlineUsers", getUsers(user.getUserName()).toArray());
		JSONObject jsonResp = new JSONObject(model);
		return jsonResp.toString();
	}


	@SuppressWarnings("unchecked")
	public void insertActiveUser(String userName) {
		PersistenceManager manager = persistenceManagerFactory
				.getPersistenceManager();
		Query query = manager.newQuery(UserInfo.class);
		query.setFilter("userName == userNameParam");
		query.declareParameters("String userNameParam");
		List<UserInfo> userEntities = (List<UserInfo>) query.execute(userName);
		UserInfo activeUser = userEntities.get(0);
		activeUser.setLastTimeStampMillis(new Date().getTime());
		manager.makePersistent(activeUser);
		manager.flush();
		manager.close();
	}

}
